import os
import traceback
from datetime import datetime
from time import time

from flask import g, jsonify, current_app

from app import executor, redisclientRemote
from app.config.secure import DOC_PATH, PERSONAL_PATH
from app.config.setting import AIGC_TASK, LOCAL_TASK, PERSONAL_DOCUMENTS_CHECK_TASK
from app.libs.ParseDocumentHtml import ParseDocumentHtml
from app.libs.ParseDocx import ParseDoc
from app.libs.PersonalDocumentsElasticsearch import DocumentEs
from app.libs.aigc_tools import PasreArticle
from app.libs.error_code import Success
from app.libs.poster import PosterGenerator
from app.libs.redprint import Redprint
from app.libs.token_auth import auth
from app.libs.tools import parseDoc, parseDocument, check_paragrpah, get_key_words, cut_sentences
from app.models.aigc_content import aigc_content
from app.models.aigc_order_info import aigc_order_info
from app.models.aigc_paragraphs import AigcParagraphs
from app.models.aigc_report_info import aigc_report_info
from app.models.base import db
from app.models.document_dom import DocumentDom
from app.models.order_info import order_info
from app.models.orders import orders
from app.models.paragraphs import Paragraphs
from app.models.personal_database import PersonalDocuments
from app.models.report_info import report_info
from app.models.sentence import sentence
from app.models.sentences_word import SentenceWord
from app.models.user import User
from app.oss.TencentOss import TencentOss
from app.validators.article import MyReportSearchForm
from app.validators.base import SearchForm
from app.validators.personal_documents import DocUploadForm, PersonalDocumentDeleteForm, PersonalCheckUploadSubmitForm, \
    PersonalCheckPasteSubmitForm
from app.validators.user import UnlockReportNumberFrom, UpdateSharedUserForm, UserInfoForm
from app.view_models.OrderInfo import OrderInfolistByTokenView
from app.view_models.PersonalDocuments import PersonalDocumentsListView

api = Redprint('user')


@api.route('/info', methods=['POST'])
@auth.login_required
def info():
    form = UserInfoForm().validate_for_api()
    user = User.query.filter_by(id=g.user.uid).first()
    return jsonify(user)

@api.route('/web_info', methods=['POST'])
@auth.login_required
def web_info():
    form = UserInfoForm().validate_for_api()
    try:
        user = User.query.filter_by(id=g.user.uid).first()
        personal_documents_count = PersonalDocuments.query.filter_by(user_id = g.user.uid).count()
        data = {
            'personal_documents_count': personal_documents_count,
            'user_info': user
        }
    except Exception as e:
        data = {
            'personal_documents_count': None,
            'user_info': None
        }
    return jsonify(data)


@api.route('/update_shared_user', methods=['POST'])
@auth.login_required
def update_shared_user():
    form = UpdateSharedUserForm().validate_for_api()
    if form.action.data == 'sharebutton':

        with db.auto_commit():
            user = User.query.filter_by(id=g.user.uid).first()
            if user and user.mp_open_id != form.fromuser.data and user.recommender == '0':
                User.query.filter_by(id=g.user.uid).update({
                    'recommender': form.fromuser.data
                })
                if user.free_chars != -1:
                    User.query.filter_by(mp_open_id=form.fromuser.data).update({
                        'free_chars': User.free_chars + 10000
                    })
                formUser = User.query.filter_by(mp_open_id=form.fromuser.data).first()
                order_info.query.filter_by(user=formUser.id).update({
                    'ai_lock': 0
                })
                aigc_order_info.query.filter_by(user=formUser.id).update({
                    'lock': 0
                })
    return Success()


@api.route('/personal_documents', methods=['POST'])
@auth.login_required
def personal_documents():
    form = SearchForm().validate_for_api()
    view = PersonalDocumentsListView()

    documents = PersonalDocuments.query.filter_by(user_id=g.user.uid).order_by(
        PersonalDocuments.create_time.desc()).paginate(
        form.page.data,
        form.limit.data,
        error_out=False)

    view.fill(documents)
    return jsonify(view)


@api.route('/personal_documents_delete', methods=['POST'])
@auth.login_required
def personal_documents_delete():
    form = PersonalDocumentDeleteForm().validate_for_api()
    documents = PersonalDocuments.query.filter_by(id=form.id.data).first()
    with db.auto_commit():
        PersonalDocuments.query.filter_by(id=form.id.data).delete()
    es = DocumentEs()
    es.delete_document(documents.osskey)
    return Success()


@api.route('/personal_document_upload', methods=['POST'])
@auth.login_required
def personnal_document_upload():
    form = DocUploadForm(g).validate_for_api()
    file_name = form.file.data.filename.replace('+', '')
    timestamp = str(int(datetime.now().timestamp()))
    localPath = PERSONAL_PATH + timestamp + '_' + file_name
    form.file.data.save(localPath)
    oss = TencentOss()
    osskey = timestamp + '_' + file_name
    oss.upload(localPath, osskey=osskey)
    content = parseDoc(localPath)
    es = DocumentEs()
    es.insertIntoEs({
        'osskey': osskey,
        'filename': file_name,
        'content': content,
        'user_id': g.user.uid,
        'delete': 0
    })
    os.remove(localPath)
    with db.auto_commit():
        personal_documents_model = PersonalDocuments()
        personal_documents_model.document = file_name
        personal_documents_model.user_id = g.user.uid
        personal_documents_model.osskey = osskey
        db.session.add(personal_documents_model)
    return Success()


@api.route('/personal_check_upload', methods=['POST'])
@auth.login_required
def personal_check_upload():
    form = DocUploadForm(g).validate_for_api()
    file_name = form.file.data.filename.replace('+', '')
    timestamp = str(int(datetime.now().timestamp()))
    localPath = DOC_PATH + timestamp + '_' + file_name
    form.file.data.save(localPath)
    data = {
        'error_code': 0,
        'filepath': localPath
    }
    return jsonify(data)


@api.route('/personal_check_submit_by_upload', methods=['POST'])
@auth.login_required
def personal_check_submit_by_uplaod():
    form = PersonalCheckUploadSubmitForm().validate_for_api()
    # content = parseDoc(form.filepath.data)
    current_time = str(round(time() * 1000))
    order_number = f'88{current_time}'
    with db.auto_commit():
        order = orders()
        order.order_number = order_number
        order.content = form.content.data
        order.author = ''
        order.char_sum = len(form.content.data)
        order.title = form.title.data
        db.session.add(order)
        report_info_model = report_info()
        report_info_model.order_number = order_number
        report_info_model.title = form.title.data
        report_info_model.author = ''
        report_info_model.chars_sum = len(form.content.data)
        report_info_model.user = g.user.uid
        report_info_model.pay_type = 'personal_documents'
        report_info_model.out_trade_no = ''
        db.session.add(report_info_model)

        info = order_info()
        info.taobao_orders = 'selfdata_free_check'
        info.order_number = order_number
        info.title = form.title.data
        info.chars_sum = len(form.content.data)
        info.author = ''
        info.file_path = form.file_path.data
        info.user = g.user.uid
        info.pay_type = 'personal_documents'
        info.out_trade_no = ''
        db.session.add(info)
    executor.submit(__db_document_operation, form.file_path.data, order_number, g.user.uid,
                    current_app._get_current_object())
    return Success()


@api.route('/personal_check_submit_by_paste', methods=['POST'])
@auth.login_required
def personal_check_submit_by_paste():
    form = PersonalCheckPasteSubmitForm().validate_for_api()
    # content = parseDoc(form.filepath.data)
    current_time = str(round(time() * 1000))
    order_number = f'99{current_time}'
    with db.auto_commit():
        order = orders()
        order.order_number = order_number
        order.content = form.content.data
        order.author = ''
        order.char_sum = len(form.content.data)
        order.title = form.title.data
        db.session.add(order)
        report_info_model = report_info()
        report_info_model.order_number = order_number
        report_info_model.title = form.title.data
        report_info_model.author = ''
        report_info_model.chars_sum = len(form.content.data)
        report_info_model.user = g.user.uid
        report_info_model.pay_type = 'personal_documents'
        report_info_model.out_trade_no = ''
        db.session.add(report_info_model)

        info = order_info()
        info.taobao_orders = 'selfdata_free_check'
        info.order_number = order_number
        info.title = form.title.data
        info.chars_sum = len(form.content.data)
        info.author = ''
        info.file_path = ''
        info.user = g.user.uid
        info.pay_type = 'personal_documents'
        info.out_trade_no = ''
        db.session.add(info)

    sentences, paragraph_content = cut_sentences(form.content.data)
    executor.submit(__db_operation, sentences, paragraph_content, order_number, g.user.uid,
                    current_app._get_current_object())
    return Success()


@api.route('/personal_check_search', methods=['POST'])
@auth.login_required
def personal_check_search():
    form = MyReportSearchForm(g).validate_for_api()
    view = OrderInfolistByTokenView()
    reports = order_info.query.filter_by(user=g.user.uid).filter_by(taobao_orders='selfdata_free_check').order_by(
        order_info.create_time.desc()).paginate(
        form.page.data,
        form.limit.data,
        error_out=False)
    view.fill(reports)
    return jsonify(view)


@api.route('/poster_url', methods=['POST'])
@auth.login_required
def poster_img():
    form = UnlockReportNumberFrom().validate_for_api()
    aigc_info = aigc_order_info.query.filter_by(order_number=form.order_number.data).first()
    if not aigc_info:
        aritcle_content = orders.query.filter_by(order_number=form.order_number.data).first()
        executor.submit(__db_submit_aigc_check, aritcle_content.title, aritcle_content.author, aritcle_content.char_sum, aritcle_content.content,
            g.user.uid, form.order_number.data, current_app._get_current_object())
    bot = PosterGenerator()
    bot.unlockAIGCPoster(form.order_number.data)
    return jsonify({'img_url': f'https://www.samereport.com/unlock_poster/unlock_aigc_{form.order_number.data}.png'})
    
    
def __db_submit_aigc_check(title, author, chars_sum, content, uid, order_number, app):
    try:
        with app.app_context():
            with db.auto_commit():
                aigc_content_model = aigc_content()
                aigc_content_model.order_number = order_number
                aigc_content_model.content = content
                aigc_content_model.author = author
                aigc_content_model.char_sum = chars_sum
                aigc_content_model.title = title
                db.session.add(aigc_content_model)

                info = aigc_order_info()
                info.taobao_orders = ''
                info.order_number = order_number
                info.title = title
                info.chars_sum = chars_sum
                info.author = author
                info.file_path = ''
                info.user = uid
                info.lock = 1
            
                db.session.add(info)

            parseModel = PasreArticle(content)
            parseModel.run()
            with db.auto_commit():
                for fragment in parseModel.ArticleStruct:
                    if fragment['content'].strip() != '':
                        paragraphModel = AigcParagraphs()
                        paragraphModel.order_number = order_number
                        paragraphModel.paragraph_index = fragment['paragraph_index']
                        paragraphModel.content = fragment['content'].strip()
                        paragraphModel.type = fragment['type']
                        db.session.add(paragraphModel)
            target_redisclient = redisclientRemote
            target_redisclient.push_task(AIGC_TASK, order_number)
    except Exception as e:
        print(e)



def __db_document_operation(file_path, order_number, user_id, app):
    with app.app_context():
        try:
            with db.auto_commit():
                parseDocument(file_path, order_number)

                Document = ParseDocumentHtml(order_number)
                Document.parseDom()
                documentDoms = DocumentDom()
                documentDoms.insert_doms(Document.domModel)

                paragraphs = DocumentDom.query.filter_by(order_number=order_number).filter_by(paragraph=1).all()
                sentences = check_paragrpah(paragraphs)
                sentenceWordModel = SentenceWord()
                sentenceWordModel.insert_sentences(sentences, order_number)
                target_redisclient = redisclientRemote
                target_redisclient.setPersonalDocumentCheckData(sentences, order_number, user_id)
                target_redisclient.push_task(PERSONAL_DOCUMENTS_CHECK_TASK, order_number)
        except Exception as e:
            traceback.print_exc()


def __db_operation(sentences, content, order_number, user_id, app):
    try:
        with app.app_context():
            with db.auto_commit():
                paragraph_model = Paragraphs()
                sentence_model = sentence()
                target_redisclient = redisclientRemote
                paragraph_model.insert_paragrahs(content, order_number)
                sentence_model.insert_sentences(sentences, order_number)
                target_redisclient.setPersonalDocumentCheckData(sentences, order_number, user_id)
                target_redisclient.push_task(PERSONAL_DOCUMENTS_CHECK_TASK, order_number)
            print('save data complete!')
    except Exception as e:
        print(e)
